package lkbaby.flowable;

import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/test")
public class MyProcess {

	@Autowired
	private RepositoryService repositoryService;

	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	private TaskService taskService;

	/**
	 * 流程部署
	 *
	 * @throws Exception
	 */
	@RequestMapping("/deploy")
	public void testDeploy() {
		Deployment deploy = repositoryService.createDeployment()
				.addClasspathResource("processes/任务回退_子流程.bpmn20.xml")
				.name("任务回退_子流程")
				.deploy();
		System.out.println("deploy.getId() = " + deploy.getId());
		System.out.println("deploy.getName() = " + deploy.getName());
		System.out.println("部署开始的时间：" + new Date());
		//TimeUnit.MINUTES.sleep(3);
	}

	/**
	 * 启动流程
	 *
	 * @throws Exception
	 */
	@RequestMapping("/startFlow")
	public void startFlow() {
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess3");
	}

	/**
	 * 完成一个任务
	 */
	@RequestMapping("/completeOne")
	public void completeTask1(@RequestParam String userKey) {
		Task task = taskService.createTaskQuery().processDefinitionKey("myProcess3").taskAssignee(userKey)
				.singleResult();
		taskService.complete(task.getId());
	}

	/**
	 * 回退
	 */
	@RequestMapping("/rollback")
	public void rollback(@RequestParam String userKey) {

		Task task = taskService.createTaskQuery().processDefinitionKey("myProcess").taskAssignee(userKey)
				.singleResult();

		System.out.println(task.getProcessInstanceId());

		// 当前task对应的用户任务ID
		List<String> currentActivityIds = new ArrayList<>();
		currentActivityIds.add(task.getTaskDefinitionKey());
		// 需要回退的目标节点的用户任务ID
		String newActivityId = "usertask3";
		// 回退操作
		runtimeService.createChangeActivityStateBuilder()
				.processInstanceId(task.getProcessInstanceId())
				.moveActivityIdsToSingleActivityId(currentActivityIds, newActivityId)
				.changeState();

	}

	/**
	 * 并行任务回退
	 */
	@RequestMapping("/rollbackParallel")
	public void rollbackParallel(@RequestParam String userKey){

		Task task = taskService.createTaskQuery().processDefinitionKey("myProcess2").taskAssignee(userKey)
				.singleResult();
		List<Task> list = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();

		System.out.println("TaskDefinitionKey list: " + list.stream().map(o -> o.getTaskDefinitionKey()).collect(Collectors.toList()));

		// 当前task对应的用户任务ID
		List<String> currentActivityIds = new ArrayList<>();
		// 需要回退的用户任务ID 当前所有分支
		currentActivityIds.addAll(list.stream().map(o -> o.getTaskDefinitionKey()).collect(Collectors.toList()));
		// 只驳回其中一个分支，在流程再次到达并行网关时，会再次创建两条并行分支，完成驳回的分支后，并行网关会直接合并分支后执行下一节点。上未执行的分支会一直存在？
		// currentActivityIds.add(task.getTaskDefinitionKey());
		// 回退目标节点的用户任务ID
		String newActivityId = "usertask1";
		// 回退操作
		runtimeService.createChangeActivityStateBuilder()
				.processInstanceId(task.getProcessInstanceId())
				.moveActivityIdsToSingleActivityId(currentActivityIds, newActivityId)
				.changeState();
	}

	/**
	 * 子流程回退
	 */
	@RequestMapping("/rollbackSubProcess")
	public void rollbackSubProcess(@RequestParam String userKey){

		Task task = taskService.createTaskQuery().processDefinitionKey("myProcess3").taskAssignee(userKey)
				.singleResult();

		System.out.println("TaskDefinitionKey：" + task.getTaskDefinitionKey());
		// 当前task对应的用户任务ID
		List<String> currentActivityIds = new ArrayList<>();
		currentActivityIds.add(task.getTaskDefinitionKey());
		// 子流程回到主流程
		String newActivityId = "usertask1";
		// 主流程回到子流程
		// String newActivityId = "usertask2";
		// 回退操作
		runtimeService.createChangeActivityStateBuilder()
				.processInstanceId(task.getProcessInstanceId())
				.moveActivityIdsToSingleActivityId(currentActivityIds, newActivityId)
				.changeState();
	}

}
